home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug103 / roff1.c < prev    next >
Text File  |  1985-03-10  |  11KB  |  448 lines

  1. /* 7 MAY 81 */
  2. /* based on the formatter presented in Kernighan and Plauger's
  3.    SOFTWARE TOOLS, modified for BDS C */
  4.  
  5.  
  6. #include "roffglob"
  7.  
  8. main(argc, argv)
  9. int argc;
  10. char **argv;
  11. {
  12. char filename[20], line[ MAXLINE ];
  13. struct _buf iobuf;
  14.  
  15.  
  16. dioinit (&argc, argv);    /* directed I/O */
  17. fprintf(STDERR,"\nVersion 5.1\n");
  18. while (0) putchar('\7');
  19.  
  20. debug = FALSE;
  21. if (argc == 1)
  22.       { fprintf(STDERR,"\nUSAGE:  format file1\n  more than one file OK ");
  23.     exit();
  24.       }
  25.  
  26. argv++;
  27. while ( --argc > 0 )
  28.       { strcpy (filename, *argv++);        /* get next argument */
  29.     fprintf(STDERR,"\nNow processing <%s>",filename );
  30.     if (filename[0] == '-' && filename[1]=='D')
  31.           {
  32.         debug=TRUE;
  33.         continue;
  34.           }
  35.  
  36.  
  37.     if (ERROR == fopen( filename, &iobuf ))
  38.           { fprintf(STDERR,"\ncan not open <%s>", filename );
  39.         continue;
  40.           }
  41.  
  42.     init_defaults();
  43.  
  44.     while ( fgets( line, &iobuf ) != 0 ) /*until EOF or CPMEOF */
  45.           { if (line[0] == COMMAND )
  46.             comand (line);
  47.         else
  48.             text (line);
  49.  
  50.           }
  51.     if (LINENO > 0  || OUTBUF[0] !='\0')
  52.         space (HUGE);        /* flush last output */
  53.     fprintf(STDERR,"\nDone processing <%s>", filename );
  54.  
  55.       }     /* end while (--argc > 0 ) */
  56. dioflush();
  57. }        /* end main()           */
  58.  
  59.  
  60. /********************************************************************
  61. initializes the global variables governing the execution of the
  62.  format commands.
  63. ********************************************************************/
  64. init_defaults()
  65. {
  66.  
  67. FILL = FI_DEF;    /* yes we want filled lines */
  68. LSVAL = LS_DEF;    /* line spacing = 1 */
  69. INVAL = IN_DEF;    /* left margin indent  0 */
  70. RMVAL = RM_DEF;    /* right margin = page width  */
  71. TIVAL = TI_DEF;    /* left margin temporary indent    0 */
  72. CEVAL = CE_DEF;    /* next n lines to be centered -  0  */
  73. ULVAL = UL_DEF;    /* next n lines to be underlined -  0  */
  74.  
  75. PAGESTOP = FALSE;
  76. PLVAL = PAGELEN;
  77. M1VAL = M1_DEF;        /* top and bottom margins */
  78. M2VAL = M2_DEF;
  79. M3VAL = M3_DEF;
  80. M4VAL = M4_DEF;
  81. CURPAG = 0;
  82. NEWPAG = 1;
  83. LINENO = 0;
  84. BOTTOM = PLVAL - M3VAL - M4VAL;
  85.  
  86. OUTWRDS = 0;    /* no. of words in outbuf */
  87. OUTBUF [0] = '\0';
  88. DIR = 0;
  89.  
  90. strcpy ( HEADER, "\n" );
  91. strcpy ( FOOTER, "\n" );
  92. }
  93.  
  94.  
  95. /*****************************************************************
  96. this function decodes the command type, returning the type, or
  97.     UNKNOWN.
  98. *******************************************************************/
  99. int comtyp (line)
  100. char *line;
  101. {
  102. char let1, let2;
  103.  
  104. let1 = toupper( line[1] );
  105. let2 = toupper( line[2] );
  106.  
  107. if ( let1=='F' && let2=='I')    return( FI );
  108. if ( let1=='F' && let2=='O')    return( FO );
  109. if ( let1=='T' && let2=='I')    return( TI );
  110. if ( let1=='B' && let2=='P')    return( BP );
  111. if ( let1=='B' && let2=='R')    return( BR );
  112. if ( let1=='C' && let2=='E')    return( CE );
  113. if ( let1=='H' && let2=='E')    return( HE );
  114. if ( let1=='I' && let2=='N')    return( IN );
  115. if ( let1=='L' && let2=='S')    return( LS );
  116. if ( let1=='N' && let2=='F')    return( NF );
  117. if ( let1=='P' && let2=='L')    return( PL );
  118. if ( let1=='R' && let2=='M')    return( RM );
  119. if ( let1=='S' && let2=='P')    return( SP );
  120. if ( let1=='U' && let2=='L')    return( UL );
  121. if ( let1=='M')
  122.       { if (let2=='1')        return( M1 );
  123.     if (let2=='2')        return( M2 );
  124.     if (let2=='3')        return( M3 );
  125.     if (let2=='4')        return( M4 );
  126.       }
  127.  
  128. return( UNKNOWN );        /* no match */
  129.  
  130. }
  131.  
  132.  
  133. /*********************************************************************
  134. Skips white-space characters at the beginning of a string.
  135. *********************************************************************/
  136. skip_blanks ( string )
  137. char *string;
  138. {
  139. char local[ MAXLINE ];
  140. int i, j, k;
  141.  
  142.  
  143.  
  144. strcpy ( local, string );
  145.  
  146. for (i=0; local[i]==' ' || local[i]=='\t' || local[i]=='\n' ; i++);
  147.  
  148. for (j=0; (string[j]=local[i]) != '\0' ; i++, j++ )    ;
  149.  
  150. return;
  151. }
  152.  
  153.  
  154. /*********************************************************************
  155.  
  156. Truncates white-space characters at the end of a string.
  157.  
  158. *********************************************************************/
  159. trunc_bl (string)
  160. char *string;
  161. {
  162. char *ptr;
  163. int k;
  164.  
  165. k = strlen (string);
  166. ptr = &string[ k-1 ];    /* char before terminating nul */
  167.  
  168. while (*ptr==BLANK || *ptr==TAB || *ptr==NEWLINE)    
  169.     *ptr--  = '\0';
  170. }
  171.  
  172.  
  173. /*******************************************************************
  174. performs the formatting command returned by comtyp - sets global
  175.   variables ( indenting, underlining, etc. )
  176. *******************************************************************/
  177.  
  178. comand ( line )
  179. char *line;
  180. {
  181. int c_type;    /* command type  */
  182. int arg_val;    /* argument value, if any */
  183. char arg_typ;    /* relative (+ or -) or absolute */
  184. int i;
  185.  
  186. c_type = comtyp (line);
  187. if DEBUG fprintf(STDERR,"\n\nCOMAND %d",c_type);
  188.  
  189. if (c_type == UNKNOWN)    /* IGNORE ALIEN ORDERS */
  190.       {
  191.     fprintf(STDERR, "UNKNOWN COMMAND: <%s>\n", line);
  192.     return;
  193.       }
  194.  
  195. arg_val = get_val ( line, &arg_typ );
  196. if DEBUG fprintf(STDERR, " \n    get_val returned arg_val=%d, arg_typ= %c   ",
  197.                    arg_val,    arg_typ   );
  198. if DEBUG fprintf(STDERR,"\n\n");
  199.  
  200. switch (c_type)
  201.       {
  202.     case FI :    /* filled lines  */
  203.         brk();    /* flush out last unfilled */
  204.         FILL = YES;
  205.         break;
  206.  
  207.     case NF :    /* non-filled lines */
  208.         brk();    /* flush out */
  209.         FILL = NO;
  210.         break;    /* down and cry */
  211.  
  212.     case BR :    /* just cause a break */
  213.         brk();
  214.         break;
  215.  
  216.     case LS :    /* set line spacing value */
  217.         set (&LSVAL, arg_val, arg_typ, LS_DEF, 1, HUGE );
  218.         break;
  219.  
  220.     case TI :    /* set temporary left indent */
  221.         brk();
  222.         set ( &TIVAL, arg_val, arg_typ, TI_DEF, 0, RMVAL );
  223.         break;
  224.  
  225.     case IN :    /* set left indent */
  226.         set ( &INVAL, arg_val, arg_typ, IN_DEF, 0, RMVAL-1 );
  227.         TIVAL = INVAL;
  228.         break;
  229.  
  230.     case RM:    /* set right margin */
  231.         set ( &RMVAL, arg_val, arg_typ, RM_DEF, TIVAL+1, HUGE );
  232.         break;
  233.     case M1:    /* set topmost margin */
  234.         set ( &M1VAL, arg_val, arg_typ, M1_DEF, 0, HUGE);
  235.         break;
  236.  
  237.     case M2:    /* set second top margin */
  238.         set ( &M2VAL, arg_val, arg_typ, M2_DEF, 0, HUGE);
  239.         break;
  240.  
  241.     case M3:    /* set first bottom margin */
  242.         set ( &M3VAL, arg_val, arg_typ, M3_DEF, 0, HUGE);
  243.         break;
  244.  
  245.     case M4:    /* set bottom-most margin */
  246.         set ( &M4VAL, arg_val, arg_typ, M4_DEF, 0, HUGE);
  247.         break;
  248.  
  249.     case CE :    /* center next arg_val lines */
  250.         brk();
  251.         set ( &CEVAL, arg_val, arg_typ, CE_DEF, 0, HUGE);
  252.         break;
  253.  
  254.     case UL :    /* underline next arg_val lines */
  255.         set ( &ULVAL, arg_val, arg_typ, UL_DEF, 1, HUGE );
  256.         break;
  257.  
  258.     case HE :    /* get header title for pages */
  259.         gettl ( line, HEADER );
  260.         break;
  261.  
  262.     case FO :    /* get footer title for pages */
  263.         gettl ( line, FOOTER );
  264.         break;
  265.  
  266.     case SP :    /* space down arg_val blank lines */
  267.         set (&SPVAL, arg_val, arg_typ, 1, 0, HUGE);
  268.         space ( SPVAL );
  269.         break;
  270.  
  271.     case BP :    /* set pageno arg_val - begin page */
  272.         if ( LINENO > 0 )    space (HUGE);
  273.         set ( &CURPAG, arg_val, arg_typ, CURPAG+1, -HUGE, HUGE);
  274.         NEWPAG = CURPAG;
  275.         break;
  276.  
  277.     case PL :    /* set page length */
  278.         set (&PLVAL, arg_val, arg_typ, PAGELEN,
  279.             M1VAL+M2VAL+M3VAL+M4VAL+1, HUGE);
  280.         BOTTOM = PLVAL - M3VAL - M4VAL;
  281.         break;
  282.  
  283.  
  284.       }
  285.  
  286. return;
  287. }
  288.  
  289. /******************************************************************
  290.  
  291. gets the number ( if any ) associated with any command 
  292.  
  293. *******************************************************************/
  294. int get_val ( line, typ )
  295. char *line, *typ;
  296. {
  297. int i;
  298. char local[ MAXLINE ];
  299.  
  300. strcpy (local, line);    /* local copy */
  301.  
  302. /* skip over the command line */
  303. for (i=1; local[i]!=' ' && local[i]!='\t' && local[i]!='\n' ; i++ )
  304. ;
  305.  
  306. skip_blanks (&local[i]);    /* find the number */
  307. *typ = local[i];    /* relative or absolute */
  308.  
  309. if ( *typ=='+' || *typ=='-' )    i++;
  310. else if ( !isdigit( *typ ) )    return( NO_VAL );
  311.  
  312. return ( atoi( &local[i] ));
  313.  
  314. }
  315.  
  316.  
  317. /*****************************************************************
  318.  sets a global parameter like line-spacing, underlining, etc.
  319.  Also checks that the new value is within the range of that 
  320.  parameter.  Assigns the default for that parameter if no value
  321.   is specified.
  322. ******************************************************************/
  323.  
  324. set ( param, val, arg_typ, defval, minval, maxval )
  325. int *param, val, defval, minval, maxval;
  326. char arg_typ;
  327. {
  328. if (val == NO_VAL )        /* defaulted */
  329.     *param = defval;
  330. else if (arg_typ == '+')    /* relative + */
  331.     *param += val;
  332. else if (arg_typ == '-')    /* relative - */
  333.     *param -= val;
  334. else    *param = val;        /* absolute */
  335.  
  336. *param = min (*param,maxval);
  337. *param = max (*param, minval);
  338.  
  339. if DEBUG fprintf(STDERR,"\n    SET *param = %d", *param);
  340. return;
  341. }
  342.  
  343.  
  344.  
  345. /**********************************************************
  346.         centers a line of text
  347. **********************************************************/
  348. center (line)
  349. char *line;
  350. {
  351. TIVAL = max(( RMVAL+TIVAL-strlen(line))/2, 0 );
  352. return;
  353. }
  354.  
  355.  
  356. /**************************************************************
  357.     get next word from input line
  358. ***************************************************************/
  359. int getwrd (in,  out )
  360. char *in, *out;
  361. {
  362. int i, j, n;
  363.  
  364. /* find first non-blank */
  365. skip_blanks (in);
  366. replace_char ( in, TAB, BLANK); /* replace tabs w/space */
  367.  
  368. /* scan off a word */
  369. if ( 1 == (n = sscanf( in, "%s ", out)))    
  370.       { if DEBUG fprintf(STDERR,"\nafter sscanf out = <%s>",out);
  371.     j = strlen (out);
  372.     replace_char (out, NEWLINE, BLANK);
  373.     for (i=0; i<j; i++ )    in[i] = BLANK;    /* blank out word in input */
  374.       }
  375. if DEBUG fprintf(STDERR,"\ngetwrd will return %d", n);
  376. return(n);    /* WE_HAVE_A_WORD = 1 */
  377. }
  378.  
  379.  
  380.  
  381.  
  382. /*****************************************************************
  383.     distibute words evenly across a line
  384. *****************************************************************/
  385. spread ( line, nextra, no_words)
  386. char *line;
  387. int nextra;    /* no. extra places left in line */
  388. int no_words;   /* no. words in the line         */
  389. {
  390. int i, j, nblanks, nholes;
  391.  
  392. if DEBUG fprintf(STDERR,"\n\nspread:line=<%s>, nextra=%d, no_words=%d",
  393.                           line,      nextra,    no_words   );
  394. if (nextra <= 0 || no_words <= 1)    return;
  395.  
  396. DIR = !(DIR);
  397. nholes = no_words - 1;
  398. trunc_bl (line);
  399. i = strlen(line) - 1 ; /* last character of string */
  400. j = min (MAXLINE - 2,  i + nextra);    /* last  position in output */
  401. line[j+1] = '\0';
  402. if DEBUG fprintf(STDERR,"\nDIR=%d, nholes=%d, i=%d, j=%d",
  403.                    DIR,    nholes,    i,    j   );
  404.  
  405. for ( ; i<j ; i--, j-- )
  406.       { line[j] = line[i];
  407.     if DEBUG fprintf(STDERR,"[%c i=%d j=%d] ", line[j], i, j);
  408.     if ( line[i] == BLANK)
  409.           { if (DIR == 0)
  410.             nblanks = (nextra - 1)/nholes   +   1;
  411.         else
  412.             nblanks = nextra/nholes;
  413.         nextra = nextra - nblanks;
  414.         nholes = nholes - 1;
  415.  
  416.         if DEBUG fprintf(STDERR,"\nnblanks=%d, nextra=%d",
  417.                                    nblanks,    nextra   );
  418.         for ( ; nblanks > 0;  nblanks-- )
  419.             line[--j] = BLANK;
  420.           }
  421.       }
  422. if DEBUG fprintf(STDERR,"\nafter spreading, line is:\n<%s>", line);
  423. return;
  424. }
  425.  
  426.  
  427. /****************************************************************
  428.     end current filled line 
  429. *****************************************************************/
  430. brk()
  431. {
  432. int l;
  433. if DEBUG fprintf(STDERR,"\nbrk: OUTBUF=<%s>", OUTBUF);
  434.  
  435. if ( 0!= ( l = strlen (OUTBUF)))
  436.       { OUTBUF[l] = NEWLINE;
  437.     OUTBUF[l+1] = '\0';
  438.     put (OUTBUF);
  439.       }
  440.  
  441. OUTWRDS = 0;
  442. OUTBUF[0] = '\0';
  443. return;
  444.  
  445. }
  446. 
  447.       { OUTBUF[l] = NEWLINE;
  448.     O